'use strict';

var vk; // 全局vk实例
// 涉及的表名
const dbName = require("../../dao/config.js");

var db = uniCloud.database(); // 全局数据库引用
var _ = db.command; // 数据库操作符
var $ = _.aggregate; // 聚合查询操作符
/**
 * 权限注意：访问以下链接查看
 * 文档地址：https://vkdoc.fsq.pub/client/uniCloud/cloudfunctions/cloudObject.html#内置权限
 */
var cloudObject = {
	isCloudObject: true, // 标记为云对象模式
	/**
	 * 请求前处理，主要用于调用方法之前进行预处理，一般用于拦截器、统一的身份验证、参数校验、定义全局对象等。
	 * 文档地址：https://vkdoc.fsq.pub/client/uniCloud/cloudfunctions/cloudObject.html#before-预处理
	 */
	_before: async function() {
		vk = this.vk; // 将vk定义为全局对象
		// let { customUtil, uniID, config, pubFun } = this.getUtil(); // 获取工具包
	},
	/**
	 * 请求后处理，主要用于处理本次调用方法的返回结果或者抛出的错误
	 * 文档地址：https://vkdoc.fsq.pub/client/uniCloud/cloudfunctions/cloudObject.html#after-后处理
	 */
	_after: async function(options) {
		let { err, res } = options;
		if (err) {
			return; // 如果方法抛出错误，直接return;不处理
		}
		return res;
	},
	/**
	 * 获取当前用户的申请状态
	 * @url client/salesman.getStatus 前端调用的url参数地址
	 */
	getStatus: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			invite_code
		} = data;
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		if (vk.pubfn.isNull(invite_code) && vk.pubfn.getData(userInfo, "fx.invite_code")) {
			invite_code = vk.pubfn.getData(userInfo, "fx.invite_code");
		}
		if (vk.pubfn.isNotNull(invite_code)) {
			let inviterUserInfo = await vk.daoCenter.userDao.findByInviteCode(invite_code);
			if (vk.pubfn.isNotNull(inviterUserInfo)) {
				res.inviterUserInfo = {
					_id: inviterUserInfo._id,
					nickname: inviterUserInfo.nickname,
					avatar: inviterUserInfo.avatar,
					gender: inviterUserInfo.gender
				};
			}
		}
		let showText = "提交申请";
		if (userInfo.fx) {
			if (userInfo.fx.status === 0) {
				showText = "请商家等待审核";
			} else if (userInfo.fx.status === 1) {
				showText = "进入业务中心";
			} else if (userInfo.fx.status === 2) {
				showText = "您的审核被拒绝，点击重新申请";
			} else if (userInfo.fx.status === 3) {
				showText = "您的资格被冻结，请联系客服处理";
			}
		}
		res.fx = userInfo.fx || {};
		res.showText = showText;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 申请分销员
	 * @url client/salesman.applySalesman 前端调用的url参数地址
	 */
	applySalesman: async function(data) {
		let res = { code: 0, msg: '' };
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		// 业务逻辑开始-----------------------------------------------------------
		let {
			real_name,
			mobile,
			invite_code,
			apply_comment,
		} = data;
		if (vk.pubfn.isNull(invite_code)) {
			return { code: -1, msg: '邀请码不能为空！' };
		}
		let mode = 1; // 1:正常分享 2:系统分享人 3:无分享人
		if (invite_code === "888888") {
			mode = 2;
		}
		let inviterUserInfo = await vk.daoCenter.userDao.findByInviteCode(invite_code);
		if (mode == 1) {
			if (vk.pubfn.isNull(inviterUserInfo)) return { code: -1, msg: '邀请码错误！' };
			if (!vk.pubfn.getData(inviterUserInfo, "fx.is_fx")) return { code: -1, msg: '对方没有推广权限！' };
		}

		let { status = -1 } = userInfo.fx || {};
		// 只有未申请过或未通过审核时才可以申请
		if ([1, 3].indexOf(status) > -1) {
			let errObj = {
				1: "您已通过审核",
				3: "您的推广资格已被冻结"
			};
			return { code: -1, msg: errObj[status] };
		}
		let time = Date.now();

		let fxJson = {
			apply_comment,
			apply_time: time,
			mobile,
			real_name,
			invite_code,
			is_fx: 0,
			status: 0, //初始值为申请中
		};
		let mchInfo = await vk.daoCenter.mchDao.find();
		let examine_mode = vk.pubfn.getData(mchInfo, "fx.examine_mode");
		res.msg = "提交成功，请等待审核。";
		res.examine_mode = examine_mode;
		if (examine_mode == 0) {
			// 0为无需审核，直接审核通过
			fxJson["is_fx"] = 1;
			fxJson["status"] = 1;
			fxJson["status_str"] = _.remove();
			fxJson["status_time"] = time;
			fxJson["lv"] = 0;
			res.msg = "审核通过，即将前往业务中心！";
		}
		await vk.daoCenter.userDao.updateAndReturn({
			whereJson: {
				_id: userInfo._id
			},
			dataJson: {
				fx: fxJson
			}
		});
		res.shareRes = await vk.daoCenter.userDao.updateInviterUser({
			userInfo: userInfo, // 被分享人
			inviterUserInfo: inviterUserInfo, // 分享人
			mode: mode, // 1:正常分享 2:系统分享人 3:无分享人
			clientInfo: this.getClientInfo(), // 日志需要
		});
		res.userInfo = await vk.daoCenter.userDao.findById(userInfo._id);
		res.needUpdateUserInfo = true;
		res.tmplIds = ["ZttnDpfQvZeu2BaqM_-rpnDp6eebXnXDsJ2nJkenT9k"];
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取业务中心数据
	 * @url client/salesman.getSalesmanCenter 前端调用的url参数地址
	 */
	getSalesmanCenter: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let { uid } = this.getClientInfo();
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		let {

		} = data;
		let time = Date.now();
		let { todayStart, todayEnd } = vk.pubfn.getCommonTime();
		let {
			is_fx = 0,
				status = 2
		} = userInfo.fx || {};
		if (is_fx != 1) return { code: -3, msg: "" };

		if (status !== 1) {
			let errObj = {
				0: "您的资格正在审核中",
				2: "您未通过审核",
				3: "您的推广资格已被冻结"
			};
			return { code: -2, msg: errObj[fx_status], userInfo };
		}
		let inviterWhere = {
			"inviter_uid.0": uid
		};
		// 累计用户数量
		let shareUserNumAll = await vk.daoCenter.userDao.count({
			...inviterWhere
		});

		// 今日推广用户数量
		let todayUser = await vk.daoCenter.userDao.count({
			...inviterWhere,
			invite_time: _.gte(todayStart).lte(todayEnd),
		});
		// 今日订单金额
		let todayOrderAmount = await vk.daoCenter.orderDao.sum({
			fieldName: "amount_info.payment_amount",
			whereJson: {
				...inviterWhere,
				pay_time: _.gte(todayStart).lte(todayEnd),
			}
		});

		// 累计订单数量
		let totalOrder = await vk.daoCenter.orderDao.count({
			...inviterWhere,
			status: _.gt(0)
		});

		// 获取总可解锁金额
		res.unlockRewardCount = await vk.daoCenter.userDao.countUnlockReward({
			user_id: uid,
			time
		});

		res.stats = {
			todayUser,
			totalOrder,
			todayOrderAmount,
			shareUserNumAll
		};

		res.share = {
			avatar: userInfo.avatar,
			title: `${userInfo.nickname}邀请您加入`,
			my_invite_code: userInfo.my_invite_code,
			qrcode: "",
			path: `/pages/login/share-register/share-register?code=${userInfo.my_invite_code}`,
			imageUrl: "https://img.alicdn.com/imgextra/i4/121022687/O1CN01F29RiF1Vigtz2E1y3_!!121022687.jpg",
			show: false
		};

		res.userInfo = userInfo;
		res.needUpdateUserInfo = true; // 通知前端需要更新用户信息
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 解锁奖励
	 * @url client/salesman.unlockReward 前端调用的url参数地址
	 */
	unlockReward: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let { uid } = this.getClientInfo();
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		let time = Date.now();
		// 尝试解锁奖励
		let unlockRes = await vk.daoCenter.moneyDao.unlockReward({
			user_id: uid
		});
		let unlockRewardMoney = unlockRes.unlockRewardMoney;
		if (!unlockRewardMoney) {
			return unlockRes;
		}
		let unlockReward = vk.pubfn.toDecimal(unlockRewardMoney / 100, 2);
		if (unlockRes.userInfo) {
			userInfo = unlockRes.userInfo;
		}
		console.log(`用户【${uid}${userInfo.nickname}】成功解锁奖励：${unlockReward} 元`);
		res.unlockReward = unlockReward;
		res.userInfo = userInfo;
		res.needUpdateUserInfo = true;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取小程序码
	 * @url client/salesman.getGenerateQRCode 前端调用的url参数地址
	 */
	getGenerateQRCode: async function(data) {
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		if (vk.pubfn.isNull(data.scene)) {
			// 若scene为空,则自动带上用户邀请码
			if (userInfo.my_invite_code) {
				data.scene = `code=${userInfo.my_invite_code}`;
			}
		}
		if (!userInfo.role || userInfo.role.indexOf("admin") === -1) {
			data.check_path = true; // 防止超限, 为 false 时允许小程序未发布或者 page 不存在， 但page 有数量上限（60000个）请勿滥用。
		}
		res = await vk.openapi.weixin.wxacode.getUnlimited(data);
		if (typeof res === "object" && res.code) {
			return res;
		}
		try {
			// 二进制转base64
			let base64 = Buffer.from(res, 'binary').toString('base64')
			return {
				code: 0,
				base64: `data:image/png;base64,${base64}`,
				tmplIds: ["NcspDBQpH6CGHos3mMADrrQpEv2gHmtfOPa5KTLs92E"]
			};
		} catch (err) {
			// 转base64失败
			return {
				code: -1,
				msg: "生成小程序码失败",
				err: {
					message: err.message,
					stack: err.stack
				}
			};
		}
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取商品信息
	 * @url client/salesman.getGoodsList 前端调用的url参数地址
	 */
	getGoodsList: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		res = await vk.daoCenter.goodsDao.getTableData({
			data,
			whereJson: {
				status: 1
			}
		});
		res.mchInfo = await vk.daoCenter.mchDao.find();
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取我分享的用户列表(我的粉丝)
	 * @url client/salesman.getUserList 前端调用的url参数地址
	 */
	getUserList: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let { uid } = this.getClientInfo();
		let {
			formData = {}
		} = data;
		let {
			type = 0, // 0 直推 1 间推
				inviter_id,
		} = formData;
		let whereJson = {};
		if (inviter_id) {
			whereJson[`inviter_uid.0`] = inviter_id;
			whereJson[`inviter_uid.1`] = uid;
		} else {
			if (type == 0) {
				whereJson[`inviter_uid.0`] = uid;
			} else if (type == 1) {
				whereJson[`inviter_uid.1`] = uid;
			} else {
				return { code: -1, msg: "参数错误" };
			}
		}
		res = await vk.daoCenter.userDao.getTableData({
			data,
			whereJson
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 添加用户绑定
	 * @url client/salesman.pub_addUserLocking 前端调用的url参数地址
	 */
	pub_addUserLocking: async function(data) {
		let res = { code: 0, msg: '' };
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		// 业务逻辑开始-----------------------------------------------------------
		let {
			invite_code, // 邀请码
		} = data;
		if (vk.pubfn.isNull(invite_code)) {
			return { code: 0, msg: "邀请码为空，无需绑定" };
		}
		if (vk.pubfn.isNull(userInfo)) {
			return { code: 0, msg: "用户未登录，无需绑定" };
		}
		let originalShareUser = await vk.daoCenter.userDao.findByInviteCode(invite_code);
		if (vk.pubfn.isNull(originalShareUser)) {
			return { code: -1, msg: "邀请码错误" };
		}
		let inviterUserInfo;
		let is_fx = vk.pubfn.getData(originalShareUser, "fx.is_fx");
		if (!is_fx) {
			// 此处需要判断如果分享者不是推广员，则客户归属分享者的推广员
			let inviter_uid = vk.pubfn.getData(originalShareUser, "inviter_uid.0");
			if (inviter_uid) {
				inviterUserInfo = await vk.daoCenter.userDao.findById(inviter_uid);
			}
		} else {
			inviterUserInfo = originalShareUser;
		}
		if (vk.pubfn.isNull(inviterUserInfo)) {
			return { code: 0, msg: "无需绑定：邀请人不存在或没有邀请资格" };
		}

		let inviter_lock = 1;
		let mchInfo = await vk.daoCenter.mchDao.find();
		if (mchInfo.fx.no_pay_allow_change_bind === 2) {
			// 始终允许抢客
			inviter_lock = 0;
		} else if (mchInfo.fx.no_pay_allow_change_bind === 1) {
			// 用户未下单前允许抢客(订单需已付款)
			// 查询invite_time之后该用户是否有下单并付款过。
			if (!userInfo.inviter_lock) {
				let count = await vk.daoCenter.orderDao.count({
					user_id: userInfo._id,
					status: _.gt(0),
					pay_time: _.gte(userInfo.invite_time)
				});
				inviter_lock = count > 0 ? 1 : 0;
			}
		} else {
			inviter_lock = 1;
		}

		if (vk.pubfn.isNotNull(userInfo.inviter_uid) && userInfo.inviter_uid[0] === inviterUserInfo._id) {
			// 更新下时间
			await vk.daoCenter.userDao.updateById({
				id: userInfo._id,
				dataJson: {
					inviter_lock,
					"fx.new_invite_time": Date.now()
				}
			});
			return { code: 0, msg: "绑定时间已更新" };
		}

		if (mchInfo.fx.no_pay_allow_change_bind !== 2) {
			// 只要 inviter_lock > 0 不管该用户有没有推荐人都不可以被绑定。
			if (userInfo.inviter_lock > 0) {
				return { code: 0, msg: "绑定失败：已被其他邀请人锁定或该用户禁止被绑定" };
			}
		}

		res = await vk.daoCenter.userDao.updateInviterUser({
			userInfo, // 被分享人
			inviterUserInfo, // 实际分享人
			originalShareUser, // 原始分享人
			mode: 1, // 1:正常分享 2:系统分享人 3:无分享人
			inviter_lock,
			clientInfo: this.getClientInfo(), // 日志需要
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取我分享的用户信息
	 * @url client/salesman.getMyShareUserInfo 前端调用的url参数地址
	 */
	getMyShareUserInfo: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id
		} = data;
		let myShareUserInfo = await vk.daoCenter.userDao.findById(_id);
		// 判断用户是否属于我
		if (!this._isMyShareUser(myShareUserInfo)) return { code: -1, msg: "无权限操作" };
		// 获取用户订单数量
		res.orderCount = await vk.daoCenter.orderDao.count({
			user_id: _id
		});
		res.myShareUserInfo = myShareUserInfo;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 修改我分享的用户的备注
	 * @url client/salesman.updateMyShareUserInfo 前端调用的url参数地址
	 */
	updateMyShareUserInfo: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id,
			remark
		} = data;
		let myShareUserInfo = await vk.daoCenter.userDao.findById(_id);
		// 判断用户是否属于我
		if (!this._isMyShareUser(myShareUserInfo)) return { code: -1, msg: "无权限操作" };
		res.myShareUserInfo = await vk.daoCenter.userDao.updateAndReturn({
			whereJson: {
				_id: _id
			},
			dataJson: {
				"fx.inviter_remark": remark
			}
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 修改社交信息
	 * @url client/salesman.updateSocialInfo 前端调用的url参数地址
	 */
	updateSocialInfo: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		let {
			mobile = "",
				weixin_no = "",
				weixin_qrcode
		} = data;
		res.userInfo = await vk.daoCenter.userDao.updateAndReturn({
			whereJson: {
				_id: uid
			},
			dataJson: {
				"social_info.mobile": mobile,
				"social_info.weixin_no": weixin_no,
				"social_info.weixin_qrcode": weixin_qrcode
			}
		});
		res.needUpdateUserInfo = true;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取客服人员列表
	 * @url client/salesman.getServiceStaffList 前端调用的url参数地址
	 */
	getServiceStaffList: async function(data) {
		let res = { code: 0, msg: '' };
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		// 业务逻辑开始-----------------------------------------------------------
		// 用户的上级也是Ta的专属客服
		// 用户表中字段is_service_staff=1的为官方客服人员
		let { pagination = {} } = data;
		let inviter_uid = vk.pubfn.getData(userInfo, "inviter_uid.0");
		let whereJson = {};
		if (vk.pubfn.isNull(inviter_uid)) {
			whereJson = {
				is_service_staff: 1
			};
		} else {
			// 如果我有推荐人，则推荐人是我的专属客服
			whereJson= _.or([{
					_id: inviter_uid
				},
				{
					is_service_staff: 1
				}
			]);
		}
		res = await vk.daoCenter.userDao.getTableData({
			data,
			whereJson
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取佣金明细
	 * @url client/salesman.getRewardRecords 前端调用的url参数地址
	 */
	getRewardRecords: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		res = await vk.daoCenter.rewardRecDao.getTableData({
			data,
			whereJson: {
				user_id: uid
			}
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取提现方式
	 * @url client/salesman.getWithdrawalWay 前端调用的url参数地址
	 */
	getWithdrawalWay: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id,
		} = data;
		res.withdrawalWayInfo = await vk.daoCenter.withdrawalWayDao.findByWhereJson({
			_id,
			user_id: uid
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取提现方式列表
	 * @url client/salesman.getWithdrawalWayList 前端调用的url参数地址
	 */
	getWithdrawalWayList: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		res = await vk.daoCenter.withdrawalWayDao.getTableData({
			data,
			whereJson: {
				user_id: uid
			}
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 添加或修改提现方式
	 * @url client/salesman.editWithdrawalWay 前端调用的url参数地址
	 */
	editWithdrawalWay: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id, // 提现方式id
			mode, // add 添加 update 修改
			type, // 提现方式 （1:支付宝,2:微信,3:银行卡)
			bank_name, // 银行名称
			bank_open, // 开户行
			account_no, // 账号
			name, // 姓名
			mobile, // 手机号
			comment, // 备注
			is_default, // 是否默认
		} = data;
		res = await vk.daoCenter.withdrawalWayDao.editWithdrawalWay({
			_id,
			user_id: uid,
			mode,
			type,
			bank_name,
			bank_open,
			account_no,
			name,
			mobile,
			comment,
			is_default
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取申请提现页面需要的数据
	 * @url client/salesman.getApplyWithdrawal 前端调用的url参数地址
	 */
	getApplyWithdrawal: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		// 业务逻辑开始-----------------------------------------------------------
		let mchInfo = await vk.daoCenter.mchDao.find();
		res.fx = mchInfo.fx;
		res.wayInfo = await vk.daoCenter.withdrawalWayDao.getMywithdrawalWayDefault(uid);
		res.userInfo = userInfo;
		res.needUpdateUserInfo = true;
		res.serviceFeeK = 0.01; // 提现手续费
		// 返回微信小程序订阅消息模板id
		res.tmplIds = ["w4oStuL2rl6Gqpy91mgN7tzk6MDt6eFPs8nofnfMcNM"];
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取默认提现方式
	 * @url client/salesman.getDefaultWithdrawalWay 前端调用的url参数地址
	 */
	getDefaultWithdrawalWay: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		res.info = await vk.daoCenter.withdrawalWayDao.findByWhereJson({
			user_id: uid,
			is_default: true
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 设置默认的提现方式
	 * @url client/salesman.setDefaultWithdrawalWay 前端调用的url参数地址
	 */
	setDefaultWithdrawalWay: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		let {
			_id
		} = data;
		// 必填参数检测
		if (vk.pubfn.isNull(_id)) {
			return { code: -1, msg: '_id不能为空' }
		}
		await vk.daoCenter.withdrawalWayDao.update({
			whereJson: {
				_id,
				user_id: uid,
			},
			dataJson: {
				is_default: true,
			}
		});
		await vk.daoCenter.withdrawalWayDao.updateMywithdrawalWayDefault({
			id: _id,
			user_id: uid,
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 删除提现方式
	 * @url client/salesman.deleteWithdrawalWay 前端调用的url参数地址
	 */
	deleteWithdrawalWay: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let { uid } = this.getClientInfo();
		let { _id } = data;
		// 必填参数检测
		if (vk.pubfn.isNull(_id)) {
			return { code: -1, msg: '_id不能为空' }
		}
		res.num = await vk.daoCenter.withdrawalWayDao.del({
			_id,
			user_id: uid,
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 申请提现
	 * @url client/salesman.applyWithdrawal 前端调用的url参数地址
	 */
	applyWithdrawal: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let { uid } = this.getClientInfo();
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		let {
			wayId,
			value,
			mode = 0
		} = data;
		// 判断可提现余额是否足够
		if (value <= 0) {
			return { code: -1, msg: '提现金额必须大于0' };
		}
		// 获取商家设置的最低多少元起才能提现
		let mchInfo = await vk.daoCenter.mchDao.find();
		// 最少提现金额(多少起提)
		let min_withdrawal_amount = vk.pubfn.getData(mchInfo, "fx.min_withdrawal_amount");
		// 每个月最多提现次数
		let max_withdrawal_num = vk.pubfn.getData(mchInfo, "fx.max_withdrawal_num");
		// 提现服务费,默认1%
		let withdrawal_service_amount = vk.pubfn.getData(mchInfo, "fx.withdrawal_service_amount", 0.01);
		if (min_withdrawal_amount && value < min_withdrawal_amount) {
			return { code: -1, msg: `每次提现金额不能小于${min_withdrawal_amount/100}元` };
		}

		if (max_withdrawal_num) {
			let { monthStart, monthEnd } = vk.pubfn.getCommonTime();
			let num = await vk.daoCenter.withdrawalRecDao.count({
				user_id: uid,
				_add_time: _.gte(monthStart).lte(monthEnd),
				status: _.in([0, 1, 2]),
				operator_id: uid
			});

			if (num >= max_withdrawal_num) {
				return { code: -1, msg: `您本月提现次数已用完，每月最多提现${max_withdrawal_num}次。` };
			}
		}

		let allow = this._getMyAllowReward(userInfo);
		if (allow < value) {
			return { code: -1, msg: `可提现余额不足，当前余额：${allow / 100}` };
		}
		// 判断提现方式是否存在
		let wayInfo = await vk.daoCenter.withdrawalWayDao.findByWhereJson({
			_id: wayId,
			user_id: uid
		});

		if (vk.pubfn.isNull(wayInfo)) {
			return { code: -1, msg: '提现方式不存在！' };
		}
		// 事务开始
		const transaction = await vk.baseDao.startTransaction();
		try {
			// 提现服务费
			let service_fee = Math.ceil(value * withdrawal_service_amount);
			let withdrawal_money; // 实际到账金额

			if (allow >= (service_fee + value)) {
				// 如果可提现余额 >= 服务费 + 当前提现金额,则 扣除 当前提现金额 + 服务费 的余额
				withdrawal_money = value;
				value = parseInt(value + service_fee);
			} else {
				// 如果可提现余额 < 服务费 + 当前提现金额,则 扣除 当前提现金额
				withdrawal_money = parseInt(value - service_fee);
			}

			let czNo = vk.pubfn.createOrderNo("NO");
			let time = Date.now();
			// 可提现余额
			await vk.daoCenter.moneyDao.updateAccountRewardForTransaction({
				db: transaction,
				user_id: uid,
				value: value,
				isAdd: false,
				no: czNo,
				title: `用户发起提现`,
				comment: ``,
				add_type: 9, // 提现
				updateTotal: false
			});

			let typeArr = ["", "支付宝", "微信", "银行卡"];
			let wayName = typeArr[wayInfo.type];
			let account_no = wayInfo.account_no;
			// 增加提现记录
			await vk.daoCenter.withdrawalRecDao.addForTransaction({
				db: transaction,
				dataJson: {
					status: 0,
					user_id: uid,
					nickname: userInfo.nickname,
					money: value,
					service_fee,
					withdrawal_money,
					no: czNo,
					title: `提现至${wayName}:${account_no}`,
					comment: ``,
					last_update_time: time,
					mode,
					withdrawal_info: wayInfo,
					operator_id: uid
				}
			});

			await transaction.commit();
			console.log(`transaction succeeded`);
		} catch (err) {
			// 事务回滚
			return await vk.baseDao.rollbackTransaction({
				db: transaction,
				err
			});
		}
		res.userInfo = await vk.daoCenter.userDao.findById(userInfo._id);
		res.needUpdateUserInfo = true;
		res.account_reward = userInfo.account_reward;
		res.msg = "提现申请成功，资金预计将在7个工作内到账！如有疑问，可联系客服。";
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 我的提现记录
	 * @url client/salesman.getWithdrawalList 前端调用的url参数地址
	 */
	getWithdrawalList: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		res = await vk.daoCenter.withdrawalRecDao.getTableData({
			data,
			whereJson: {
				user_id: uid
			}
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取我的业绩明细（带合计功能）
	 * @url client/salesman.getPerformanceGroup 前端调用的url参数地址
	 */
	getPerformanceGroup: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		let {
			pagination = {},
				formData = {}
		} = data;
		let { pageIndex, pageSize } = pagination;
		let {
			pay_time = [],
				nickname,
				no,
		} = formData;

		let startTime = pay_time[0];
		let endTime = pay_time[1];

		// 默认查看当月的
		let time = Date.now();
		let { monthStart, monthEnd } = vk.pubfn.getCommonTime();
		if (vk.pubfn.isNullOne(startTime, endTime)) {
			startTime = monthStart;
			endTime = monthEnd;
		}
		if ((endTime - startTime) > 1000 * 3600 * 24 * 370) {
			return { code: -1, msg: '最长时间段为1年' };
		}
		let pubWhere = {
			pay_time: _.gte(startTime).lte(endTime),
		};
		if (vk.pubfn.isNotNull(nickname)) {
			try {
				pubWhere["nickname"] = new RegExp(nickname)
			} catch (err) {}
		}
		if (vk.pubfn.isNotNull(no)) {
			pubWhere["no"] = no;
		}

		let whereJson = {
			...pubWhere,
			"inviter_uid.0": uid
		}

		let groupJson = {
			_id: "$user_id", // _id是分组id， $ 后面接字段名，如user_id字段进行分组
			goods_payment_amount: $.sum("$amount.goods_payment_amount"), // 商品实付金额(业绩) 单位分 会包含余额支付的部分
			refund_goods_payment_amount: $.sum("$amount.refund_goods_payment_amount"), // 商品退款
			cacl_goods_payment_amount: $.sum($.sum(["$amount.goods_payment_amount", "$amount.refund_goods_payment_amount"])),
			title: $.first("$title"),
			nickname: $.first("$nickname"),
		};

		res = await vk.daoCenter.userGoodsPerDao.selects({
			pageIndex,
			pageSize,
			// 主表where条件
			whereJson,
			groupJson,
			sortArr: [{ name: "cacl_goods_payment_amount", type: "desc" }], // 对分组后的结果进行排序
			// 副表列表
			foreignDB: [{
				dbName: dbName.user,
				localKey: "_id",
				foreignKey: "_id",
				as: "userInfo",
				limit: 1,
				fieldJson: {
					nickname: 1,
					avatar: 1,
					social_info: 1,
					"fx.real_name": 1
				},
			}]
		});
		let stats = {};
		if (pageIndex === 1) {
			// 需要合计
			let res1 = await vk.baseDao.selects({
				dbName: dbName.userGoodsPer,
				getMain: true,
				getOne: true,
				// 主表where条件
				whereJson: {
					...pubWhere,
					"inviter_uid.0": uid
				},
				groupJson: {
					_id: "$inviter_uid.0", // _id是分组id， $ 后面接字段名，如user_id字段进行分组
					cacl_goods_payment_amount: $.sum($.sum(["$amount.goods_payment_amount", "$amount.refund_goods_payment_amount"])),
				}
			});
			stats.cacl_goods_payment_amount_1 = res1 && res1.cacl_goods_payment_amount || 0;

			let res2 = await vk.baseDao.selects({
				dbName: dbName.userGoodsPer,
				getMain: true,
				getOne: true,
				// 主表where条件
				whereJson: {
					...pubWhere,
					"inviter_uid.1": uid
				},
				groupJson: {
					_id: "$inviter_uid.1", // _id是分组id， $ 后面接字段名，如user_id字段进行分组
					cacl_goods_payment_amount: $.sum($.sum(["$amount.goods_payment_amount", "$amount.refund_goods_payment_amount"])),
				}
			});
			stats.cacl_goods_payment_amount_2 = res2 && res2.cacl_goods_payment_amount || 0;
		}
		res.stats = stats;
		res.query = {
			startTime,
			endTime
		}
		res.lastUpdateTime = time;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取业绩明细
	 * @url client/salesman.getPerformanceRecord 前端调用的url参数地址
	 */
	getPerformanceRecord: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		let {
			formData = {}
		} = data;
		let {
			type = 1,
				user_id,
		} = formData;
		type = Number(type);
		let whereJson = {};
		if (vk.pubfn.isNotNull(user_id)) {
			let userInfo = await vk.daoCenter.userDao.findById(user_id);
			let inviter_uid = vk.pubfn.getData(userInfo, "inviter_uid.0");
			if (inviter_uid !== uid) {
				return { code: -1, msg: "无权限" };
			}
			if (type === 0) {
				// 查询直推用户自己的业绩
				whereJson["user_id"] = user_id;
			} else if (type === 1) {
				// 查询直推用户直推的业绩
				whereJson[`inviter_uid.0`] = user_id;
			} else {
				return { code: -1, msg: "参数错误" };
			}
		} else {
			if (type === 2) {
				// 查询我的间推用户业绩明细
				whereJson[`inviter_uid.1`] = uid;
			} else {
				// 查询我的直推用户业绩明细
				whereJson[`inviter_uid.0`] = uid;
			}
		}
		res = await vk.daoCenter.userGoodsPerDao.getTableData({
			data,
			whereJson
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取商品业绩明细
	 * @url client/salesman.getGoodsPerformanceRecord 前端调用的url参数地址
	 */
	getGoodsPerformanceRecord: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		let {
			formData = {}
		} = data;
		let {
			type = 1,
				user_id,
		} = formData;
		type = Number(type);
		let whereJson = {};
		if (vk.pubfn.isNotNull(user_id)) {
			let userInfo = await vk.daoCenter.userDao.findById(user_id);
			let inviter_uid = vk.pubfn.getData(userInfo, "inviter_uid.0");
			if (inviter_uid !== uid) {
				return { code: -1, msg: "无权限" };
			}
			if (type === 0) {
				// 查询直推用户自己的业绩
				whereJson["user_id"] = user_id;
			} else if (type === 1) {
				// 查询直推用户直推的业绩
				whereJson[`inviter_uid.0`] = user_id;
			} else {
				return { code: -1, msg: "参数错误" };
			}
		} else {
			if (type === 2) {
				// 查询我的间推用户业绩明细
				whereJson[`inviter_uid.1`] = uid;
			} else {
				// 查询我的直推用户业绩明细
				whereJson[`inviter_uid.0`] = uid;
			}
		}
		res = await vk.daoCenter.userGoodsPerDao.getTableData({
			data,
			whereJson,
			groupJson: {
				_id: {
					goods_id: '$goods_id',
					sku_id: '$sku_id'
				},
				buy_num: $.sum('$buy_num'),
				refund_num: $.sum('$refund_num'),
				calc_num: $.sum($.sum(["$buy_num", "$refund_num"])),
				goods_id: $.first("$goods_id"),
				goods_name: $.first("$goods_name"),
				image: $.first("$image"),
				sku_id: $.first("$_id"),
				sku_name: $.first("$sku_name"),
				goods_payment_amount: $.sum("$amount.goods_payment_amount"),
				refund_goods_payment_amount: $.sum("$amount.refund_goods_payment_amount"),
				calc_goods_payment_amount: $.sum($.sum(["$amount.goods_payment_amount", "$amount.refund_goods_payment_amount"])),
			},
			sortArr: [{ name: "calc_goods_payment_amount", type: "desc" }]
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取粉丝订单
	 * @url client/salesman.getUserOrder 前端调用的url参数地址
	 */
	getUserOrder: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		res = await vk.daoCenter.orderDao.getTableData({
			data,
			whereJson: _.and([{
					pay_time: _.gte(0),
				},
				_.or([{
						"inviter_uid.0": uid
					},
					{
						"inviter_uid.1": uid
					}
				])
			])
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 获取我的分销等级
	 * @url client/salesman.getMyFxLvInfo 前端调用的url参数地址
	 */
	getMyFxLvInfo: async function(data) {
		let { uid } = this.getClientInfo(); // 获取客户端信息
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		res.mchInfo = await vk.daoCenter.mchDao.find();
		// 获取累计消费（已确认收货或已完成的）
		res.total_order_amount = await vk.daoCenter.orderDao.sumReceiptAmount(uid);
		// 获取累计消费（冻结中，未确认收货或未完成的）
		res.sumNotReceiptAmount = await vk.daoCenter.orderDao.sumNotReceiptAmount(uid);

		// 获取累计直推业绩
		let per1 = await vk.daoCenter.userGoodsPerDao.sumShare1PerByUserId({
			user_id: uid
		});
		res.total_per_1 = per1.calc_goods_payment_amount;

		// 获取累计直推人数
		res.total_share_1 = await vk.daoCenter.userDao.countShare1ByUserId({
			user_id: uid,
		});

		res.total_recharge_amount = vk.pubfn.getData(userInfo, "account_balance.total", 0);

		res.userInfo = userInfo;
		res.needUpdateUserInfo = true;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 升级
	 * @url client/salesman.upgradeLv 前端调用的url参数地址
	 */
	upgradeLv: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		// 业务逻辑开始-----------------------------------------------------------
		let {
			lv
		} = data;
		let time = Date.now();
		let mchInfo = await vk.daoCenter.mchDao.find();
		let level_rule = mchInfo.fx.level_rule;
		let item = vk.pubfn.getListItem(level_rule, "lv", lv);

		res = await this._isUpgradeFxLv({
			lvInfo: item,
			userInfo
		});

		if (res.isUpgrade) {
			// 允许升级
			await vk.daoCenter.userDao.updateFxLv({
				userInfo,
				lv: lv
			});

			res.msg = `等级已升级为【${item.name}】`;
		}
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 自动升级分销等级
	 * @url client/salesman.autoUpgradeLv 前端调用的url参数地址
	 */
	autoUpgradeLv: async function(data) {
		let userInfo = await this.getUserInfo();
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let time = Date.now();
		let mchInfo = await vk.daoCenter.mchDao.find();
		let level_rule = mchInfo.fx.level_rule;
		// 从大到小循环
		for (let i = level_rule.length - 1; i >= 0; i--) {
			let item = level_rule[i];
			let upgradeRes = await this._isUpgradeFxLv({
				lvInfo: item,
				userInfo
			});
			if (upgradeRes.isUpgrade) {
				// 允许升级
				await vk.daoCenter.userDao.updateFxLv({
					userInfo,
					lv: upgradeRes.lv
				});
				res.userInfo = await vk.daoCenter.userDao.findById(userInfo._id);
				res.needUpdateUserInfo = true;
				res.isUpgrade = upgradeRes.isUpgrade;
				res.lvInfo = item;
				res.msg = `等级已升级为【${item.name}】`;
				break;
			}
		}
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 模板函数
	 * @url client/salesman.test 前端调用的url参数地址
	 */
	test: async function(data) {
		let res = { code: 0, msg: '' };
		let { uid } = this.getClientInfo();
		let userInfo = await this.getUserInfo(); // 获取当前登录的用户信息
		// 业务逻辑开始-----------------------------------------------------------

		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 判断是否可以升级到该分销等级
	 */
	_isUpgradeFxLv: async function(data) {
		// 业务逻辑开始-----------------------------------------------------------
		let res = { code: 0, msg: "", isUpgrade: false };
		let {
			lvInfo,
			userInfo
		} = data;
		let { lv, total_recharge_amount, total_order_amount } = lvInfo;
		if (lv <= userInfo.fx.lv) {
			// 如果当前等级未高于用户目前等级，则直接返回false
			return false;
		}
		if (!userInfo.fx.is_fx) {
			return false;
		}
		let key1;
		let key2;
		let key3;

		if (total_recharge_amount > 0 && userInfo.account_balance.total > total_recharge_amount) {
			key1 = true;
		}
		let sumReceiptAmount = await vk.daoCenter.orderDao.sumReceiptAmount(userInfo._id);
		if (total_order_amount > 0 && sumReceiptAmount > total_order_amount) {
			key1 = true;
		}
		if (!key1) return { code: -1, msg: `条件1未达标`, isUpgrade: false };

		// 获取累计直推业绩
		let per1 = await vk.daoCenter.userGoodsPerDao.sumShare1PerByUserId({
			user_id: userInfo._id
		});
		let total_per_1 = per1.calc_goods_payment_amount;
		key2 = total_per_1 >= lvInfo.total_per_1 ? true : false;

		if (!key2) return { code: -1, msg: `条件2未达标：直推业绩进度（${vk.pubfn.priceFilter(total_per_1)}/${vk.pubfn.priceFilter(lvInfo.total_per_1)}）`, isUpgrade: false };

		// 获取累计直推人数
		let total_share_1 = await vk.daoCenter.userDao.countShare1ByUserId({
			user_id: userInfo._id,
		});
		key3 = total_share_1 >= lvInfo.total_share_1 ? true : false;

		if (!key3) return { code: -1, msg: `条件3未达标：直推人数进度（${total_share_1}/${lvInfo.total_share_1}）`, isUpgrade: false };
		res.isUpgrade = true;
		res.lv = lv;
		// 业务逻辑结束-----------------------------------------------------------
		return res;

	},
	// 判断是否是我的直推
	_isMyShareUser: function(myShareUserInfo) {
		let { uid } = this.getClientInfo();
		// 业务逻辑开始-----------------------------------------------------------
		if (vk.pubfn.getData(myShareUserInfo, "inviter_uid.0") === uid) {
			return true;
		} else {
			return false;
		}
		// 业务逻辑结束-----------------------------------------------------------
	},
	/**
	 * 获取我的上级
	 * let inviterUser = await this._getMyInviterUser(userInfo);
	 */
	_getMyInviterUser: async function(userInfo) {
		// 业务逻辑开始-----------------------------------------------------------
		let inviter_uid = vk.pubfn.getData(userInfo, "inviter_uid.0");
		let inviterUser;
		if (inviter_uid) {
			inviterUser = await vk.daoCenter.userDao.findById(inviter_uid);
		}
		return inviterUser;
		// 业务逻辑结束-----------------------------------------------------------
	},
	// 获取我的可提现余额
	_getMyAllowReward: function(userInfo = {}) {
		return vk.pubfn.getData(userInfo, "account_reward.allow", 0);
	},
};

module.exports = cloudObject;
